package com.example.ymm.component;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.example.ymm.bo.YmUserDetails;
import com.example.ymm.config.IgnoreUrlsConfig;
import com.example.ymm.model.CommonResult;
import com.example.ymm.model.UserLogin;
import com.example.ymm.model.em.EmLoginPlatform;
import com.example.ymm.util.*;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.*;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter;


import java.io.IOException;

/**
 * JWT登录授权过滤器
 */
@Slf4j
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
    private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);
    /**
     * 后续拆分成微服务,改为Feign调用Member服务获取UserDetail
     * 由<link>com.macro.mall.security.config.SecurityConfig<link/>子类注入
     */
//    @Autowired
//    private UserDetailsService userDetailsService;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Value("${jwt.tokenHeader}")
    private String tokenHeader;
    @Value("${jwt.tokenHead}")
    private String tokenHead;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    IgnoreUrlsConfig ignoreUrlsConfig;

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws ServletException, IOException {
        String authHeader = request.getHeader(this.tokenHeader);
        if(UtilValidate.isEmpty(authHeader)){
            authHeader =request.getParameter(this.tokenHeader);
        //    System.out.println("---从请求体里面拿token"+authHeader);
        }
        String servletPath = request.getServletPath();
//        System.out.println("--servletPath:" + servletPath);
//        System.out.println("--authHeader:"+authHeader);
        boolean whiteListed = isWhiteListed(servletPath);

        if (authHeader != null && authHeader.startsWith(this.tokenHead) && !whiteListed) {
            String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
            String username = jwtTokenUtil.getUserNameFromToken(authToken.trim());
            String userId = jwtTokenUtil.getUserIdFromToken(authToken.trim());
            Integer platform = jwtTokenUtil.getPlatformFromToken(authToken.trim());
            if (userId != null) {

                UserLogin userLogin = null;
                String s = "";

                if(UtilValidate.isNotEmpty(platform)){
                    if (platform == EmLoginPlatform.pc_3.getType()) {
                        s = redisUtil.get(RedisKeyManager.pc_token_key + authToken, String.class);
                    }
                }else{
                    s = redisUtil.get(RedisKeyManager.user_token_key + userId + ":" + authToken, String.class);
                }


                if (UtilValidate.isNotEmpty(s)) {
                    userLogin = JSONObject.parseObject(s, UserLogin.class);
                    YmUserDetails userDetails = new YmUserDetails(userLogin);
                    if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                        LOGGER.info("authenticated user:{}", username);
                        SecurityContextHolder.getContext().setAuthentication(authentication);
                    }
                } else {
                    log.info("--无法获取登录用户信息 platform：" + platform);
//                    unauthorizedResult(response);
                    response.setContentType("application/json; charset=utf-8");
                    response.setCharacterEncoding("UTF-8");
                    response.setStatus(200);
                    response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized("token已失效")));
                    response.getWriter().flush();
                    return;
                }

            } else {
                log.info("--无法获取登录用户信息 user_id ");
                unauthorizedResult(response);
                return;
            }
        } else if (!whiteListed) {
            Profiles profiles = Profiles.of("dev", "prod-new");
            //通过environment.acceptsProfiles()判断是否处在自己设定的环境当中
            Environment environment = SpringTool.getApplicationContext().getEnvironment();
            boolean swaggerEnabled = environment.acceptsProfiles(profiles);
            if (!swaggerEnabled) {
                System.out.println(servletPath);
                log.info("--前端退出登录 ");
                unauthorizedResult(response);
                return;
            }
            if(servletPath.contains("/hl")){
                unauthorizedResult(response);
                return;
            }

        }
        if (whiteListed) {
            log.info("--白名单路径:" + servletPath);
        }
        chain.doFilter(request, response);
    }

    private void unauthorizedResult(HttpServletResponse response) {
        response.setContentType("application/json; charset=utf-8");
        response.setCharacterEncoding("UTF-8");
        response.setStatus(200);
        try {
            response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized("token已失效")));
            response.getWriter().flush();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

    }


    /**
     * 检查请求路径是否为白名单中的路径
     *
     * @param path 请求路径
     * @return 如果路径匹配白名单正则表达式，返回true；否则返回false
     */
    public boolean isWhiteListed(String path) {

        String[] st = {"/userLogin", "/common", ".html", "/test","/user/book/pageList","/excel","/api"
        };
        for (String s : st) {
            if (path.contains(s)) {
                return true;
            }
        }
        return false;
    }
}
